home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / Visual Cafe Pro v1.0 / SOURCE.BIN / Animator.java < prev    next >
Encoding:
Java Source  |  1997-06-19  |  11.9 KB  |  476 lines

  1. package symantec.itools.multimedia;
  2.  
  3.  
  4. import java.awt.Graphics;
  5. import java.awt.MediaTracker;
  6. import java.awt.Canvas;
  7. import java.awt.Image;
  8. import java.awt.Dimension;
  9. import java.net.URL;
  10. import java.util.Vector;
  11. import java.util.Enumeration;
  12.  
  13. //    01/29/97    TWB    Integrated changes from Windows
  14.  
  15. /**
  16.  * This is a simple animation component. <br>
  17.  * It creates an animation by displaying a series of images in sequence.
  18.  * The programmer can specify the delay between frames in milliseconds.
  19.  * The animation can loop for a specific
  20.  * number of iterations or can run forever.
  21.  *
  22.  * @version 1.0, Nov 26, 1996
  23.  * @author Symantec
  24.  */
  25.  
  26. public class Animator
  27.     extends Canvas
  28.     implements Runnable
  29. {
  30.     /**
  31.      * Delay time between images, in milliseconds.
  32.      */
  33.     protected int delay;
  34.  
  35.     /**
  36.      * Number of times to show the animation sequence.
  37.      */
  38.     protected int numLoops;
  39.  
  40.     /**
  41.      * Run animation forever. If false, use numLoops.
  42.      */
  43.     protected boolean forever;
  44.  
  45.     /**
  46.      * Images to be displayed.
  47.      */
  48.     protected Vector images;
  49.  
  50.     /**
  51.      * Image currently being shown.
  52.      */
  53.     protected Image currentImage;
  54.  
  55.     /**
  56.      * Thread which runs the animation.
  57.      */
  58.     protected Thread displayThread;
  59.  
  60.     /**
  61.      * Dimension of largest image in sequence.
  62.      */
  63.     protected int maxWidth, maxHeight;
  64.  
  65.     /**
  66.      * Clear frame between each image.
  67.      */
  68.     protected boolean clearFrame;
  69.  
  70.     /**
  71.      * Preview this component at design time.
  72.      */
  73.     protected boolean previewMode;
  74.  
  75.     /**
  76.      * Constructs a default Animator.  The animator defaults to a 500 millisecond delay, and loops forever.
  77.      */
  78.     public Animator()
  79.     {
  80.         delay         = 500;
  81.         maxWidth      = 0;
  82.         maxHeight     = 0;
  83.         numLoops      = 1;
  84.         forever       = true;
  85.         images        = new Vector();
  86.         currentImage  = null;
  87.         clearFrame    = false;
  88.         previewMode   = false;
  89.     }
  90.  
  91.     /**
  92.      * Sets the delay between animation frames.
  93.      * @param i animation delay, in milliseconds
  94.      * @see #getDelay
  95.      */
  96.     public void setDelay(int i)
  97.     {
  98.         delay = i;
  99.     }
  100.  
  101.     /**
  102.      * Returns the current delay between animation frames.
  103.      * @return current animation delay, in milliseconds
  104.      * @see #setDelay
  105.      */
  106.     public int getDelay()
  107.     {
  108.         return delay;
  109.     }
  110.  
  111.     /**
  112.      * Sets the number of loops to perform when displaying
  113.      * the animation set.
  114.      * @param i loop count
  115.      * @see #getNumLoops
  116.      */
  117.     public void setNumLoops(int i)
  118.     {
  119.         numLoops = i;
  120.     }
  121.  
  122.     /**
  123.      * Returns the current animation set loop count.
  124.      * @return loop count
  125.      * @see #setNumLoops
  126.      */
  127.     public int getNumLoops()
  128.     {
  129.         return numLoops;
  130.     }
  131.  
  132.     /**
  133.      * Sets the repeat mode setting.
  134.      * @param b repeat mode, repeats if true
  135.      * @see #getRepeatMode
  136.      */
  137.     public void setRepeatMode(boolean b)
  138.     {
  139.         forever = b;
  140.     }
  141.  
  142.     /**
  143.      * Returns the current repeat mode setting.
  144.      * @return current repeat mode setting, true if repeat forever
  145.      * @see #setRepeatMode
  146.      */
  147.     public boolean getRepeatMode()
  148.     {
  149.         return forever;
  150.     }
  151.  
  152.     void imageLoadWait(Image image)
  153.     {
  154.         MediaTracker tracker = new MediaTracker(this);
  155.  
  156.         tracker.addImage(image, 0);
  157.  
  158.         try
  159.         {
  160.             tracker.waitForAll();
  161.         }
  162.         catch(InterruptedException e)
  163.         {
  164.         }
  165.  
  166.         int size;
  167.  
  168.         if ((size = image.getWidth(this)) > maxWidth)
  169.             maxWidth = size;
  170.  
  171.         if ((size = image.getHeight(this)) > maxHeight)
  172.             maxHeight = size;
  173.     }
  174.  
  175.     /**
  176.      * Adds an image to the animation set.
  177.      * @param url URL of the image to add
  178.      */
  179.     public synchronized void addImage(URL url)
  180.     {
  181.         Image image = getToolkit().getImage(url);
  182.  
  183.         boolean loadWait = images.size() == 0 || previewMode || !symantec.beans.Beans.isDesignTime();
  184.  
  185.         if (loadWait)
  186.         {
  187.             imageLoadWait(image);
  188.         }
  189.  
  190.         images.addElement(new AnimatorImage(url, image, loadWait));
  191.     }
  192.  
  193.     /**
  194.      * Sets the image list.  Images in this list are displayed in
  195.      * sequence to form the animation.
  196.      * @param list array of image URLs
  197.      * @see #getImageList
  198.      */
  199.     public synchronized void setImageList(URL[] list)
  200.     {
  201.         boolean wasAnimating = displayThread != null;
  202.  
  203.         if (wasAnimating)
  204.         {
  205.             stopAnimation();
  206.             displayThread = null;
  207.         }
  208.  
  209.         currentImage = null;
  210.         images = new Vector();
  211.  
  212.         for (int i = 0; i < list.length; ++i)
  213.         {
  214.             addImage(list[i]);
  215.         }
  216.  
  217.         if (wasAnimating || previewMode || !symantec.beans.Beans.isDesignTime())
  218.         {
  219.             startAnimation();
  220.         }
  221.         else if (list.length > 0)
  222.         {
  223.             currentImage = ((AnimatorImage)images.elementAt(0)).image;
  224.         }
  225.  
  226.         repaint();
  227.     }
  228.  
  229.     /**
  230.      * Returns the image list.
  231.      * @return URL list of images
  232.      * @see #setImageList
  233.      */
  234.     public synchronized URL[] getImageList()
  235.     {
  236.         URL[] list = new URL[images.size()];
  237.  
  238.         int i = 0;
  239.         Enumeration enum = images.elements();
  240.         while (enum.hasMoreElements())
  241.         {
  242.             list[i] = ((AnimatorImage)enum.nextElement()).url;
  243.         }
  244.  
  245.         return list;
  246.     }
  247.  
  248.     /**
  249.      * Sets whether or not the animation frame area is cleared
  250.      * between each frame.
  251.      * @param b if true, the frame area is cleared between each
  252.      * animation frame; if false, the frame area is not cleared.
  253.      * @see #getClearFrame
  254.      */
  255.     public void setClearFrame(boolean b)
  256.     {
  257.         clearFrame = b;
  258.     }
  259.  
  260.     /**
  261.      * Gets the current clear frame setting.
  262.      * @return boolean - if true, the frame area is cleared
  263.      * between each animation frame; if false, the frame area
  264.      * is not cleared.
  265.      * @see #setClearFrame
  266.      */
  267.     public boolean getClearFrame()
  268.     {
  269.         return clearFrame;
  270.     }
  271.  
  272.     /**
  273.      * Starts the animation.
  274.      * @see #stopAnimation
  275.      */
  276.     public void startAnimation()
  277.     {
  278.         if (displayThread == null)
  279.         {
  280.             displayThread = new Thread(this);
  281.             displayThread.start();
  282.         }
  283.     }
  284.  
  285.     /**
  286.      * Stops the animation.
  287.      * @see #startAnimation
  288.      */
  289.     public void stopAnimation()
  290.     {
  291.         if (displayThread != null)
  292.         {
  293.             displayThread.stop();
  294.             displayThread = null;
  295.         }
  296.     }
  297.  
  298.     /**
  299.      * Sets the preview mode flag.  This flag is used by Visual Cafe to
  300.      * determine if this component should be run during design time.
  301.      * @param f new preview mode
  302.      * @see #getPreviewMode
  303.      */
  304.     public void setPreviewMode(boolean f)
  305.     {
  306.         if (symantec.beans.Beans.isDesignTime())
  307.         {
  308.             previewMode = f;
  309.  
  310.             if (previewMode && (images.size() > 0))
  311.                 startAnimation();
  312.             else
  313.                 stopAnimation();
  314.         }
  315.     }
  316.  
  317.     /**
  318.      * Gets the preview mode flag. This flag is used by Visual Cafe to
  319.      * determine if this component should be run during design time.
  320.      * @param f new preview mode
  321.      * @see #setPreviewMode
  322.      */
  323.     public boolean getPreviewMode()
  324.     {
  325.         return previewMode;
  326.     }
  327.  
  328.     /**
  329.      * Body of Animation Thread.  This method is called by the Java Virtual Machine
  330.      * in response to a call to the start method of this object.
  331.      */
  332.  
  333.     public synchronized void run()
  334.     {
  335.         for (int i = 0; i < numLoops || forever; ++i)
  336.         {
  337.             if (images.size() == 0)
  338.             {
  339.                 try
  340.                 {
  341.                     wait(delay);
  342.                 }
  343.                 catch(InterruptedException e)
  344.                 {
  345.                 }
  346.  
  347.             }
  348.             else
  349.             {
  350.  
  351.                 for (int j = 0; j < images.size(); ++j)
  352.                 {
  353.                    synchronized(this)
  354.                    {
  355.                         try
  356.                         {
  357.                             wait(delay);
  358.                         }
  359.                         catch(InterruptedException e)
  360.                         {
  361.                         }
  362.  
  363.                         AnimatorImage ai = (AnimatorImage)images.elementAt(j);
  364.  
  365.                         if (!ai.loaded)
  366.                         {
  367.                             imageLoadWait(ai.image);
  368.                             images.setElementAt(new AnimatorImage(ai.url, ai.image, true), j);
  369.                         }
  370.  
  371.                         currentImage = ai.image;
  372.                     }
  373.  
  374.                     repaint();
  375.                 }
  376.             }
  377.         }
  378.     }
  379.  
  380.     /**
  381.      * Paints this component using the given graphics context.
  382.      * This is a standard Java AWT method which typically gets called
  383.      * by the AWT to handle painting this component. It paints this component
  384.      * using the given graphics context. The graphics context clipping region
  385.      * is set to the bounding rectangle of this component and its <0,0>
  386.      * coordinate is this component's top-left corner.
  387.      *
  388.      * @param g the graphics context used for painting
  389.      * @see java.awt.Component#repaint
  390.      * @see #update
  391.      */
  392.     public synchronized void paint(Graphics g)
  393.     {
  394.         if (currentImage != null)
  395.             g.drawImage(currentImage, 0, 0, this);
  396.     }
  397.  
  398.     /**
  399.      * Handles redrawing of this component on the screen.
  400.      * This is a standard Java AWT method which gets called by the Java
  401.      * AWT (repaint()) to handle repainting this component on the screen.
  402.      * The graphics context clipping region is set to the bounding rectangle
  403.      * of this component and its <0,0> coordinate is this component's
  404.      * top-left corner.
  405.      * Typically this method paints the background color to clear the
  406.      * component's drawing space, sets graphics context to be the foreground
  407.      * color, and then calls paint() to draw the component.
  408.      *
  409.      * It is overridden here to make clearing the background before painting
  410.      * optional. If the clearFrame flag is true the background will be erased
  411.      * before painting begins.
  412.      *
  413.      * @param g the graphics context
  414.      * @see java.awt.Component#repaint
  415.      * @see #paint
  416.      */
  417.     public void update(Graphics g)
  418.     {
  419.         if (clearFrame)
  420.             super.update(g);
  421.         else
  422.             paint(g);
  423.     }
  424.  
  425.     /**
  426.      * Returns the recommended dimensions to properly display this component.
  427.      * This is a standard Java AWT method which gets called to determine
  428.      * the recommended size of this component.
  429.      *
  430.      * @return  If no images have been loaded, a dimension of 10 by 10 is returned.
  431.      *          If one or more images have been loaded, the largest height and the
  432.      *          largest width of any image is returned.
  433.      *
  434.      * @see #minimumSize
  435.      */
  436.     public Dimension preferredSize()
  437.     {
  438.         if (images == null || images.size() == 0)
  439.             return new Dimension(10, 10);
  440.  
  441.         return new Dimension(maxWidth, maxHeight);
  442.     }
  443.  
  444.     /**
  445.      * Returns the minimum dimensions to properly display this component.
  446.      * This is a standard Java AWT method which gets called to determine
  447.      * the minimum size of this component.
  448.      *
  449.      * @return If no images have been loaded, a dimension of 10 by 10 is returned.
  450.      *         If one or more images have been loaded, the largest height and the
  451.      *         largest width of any image is returned.
  452.      *
  453.      * @see #preferredSize
  454.      */
  455.     public Dimension minimumSize()
  456.     {
  457.         return preferredSize();
  458.     }
  459. }
  460.  
  461.  
  462. class AnimatorImage
  463. {
  464.     URL url;
  465.     Image image;
  466.     boolean loaded;
  467.  
  468.     public AnimatorImage(URL u, Image i, boolean l)
  469.     {
  470.         url    = u;
  471.         image  = i;
  472.         loaded = l;
  473.     }
  474. }
  475.  
  476.